package com.pubinfo.passbook.common.service.ruler.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.pubinfo.passbook.common.entity.TRuleFormula;
import com.pubinfo.passbook.common.mapper.TRuleUserWiteoffMapper;
import com.pubinfo.passbook.common.mapper.TSubsidiaryInfoMapper;
import com.pubinfo.passbook.common.model.bo.witeoff.CityInfo;
import com.pubinfo.passbook.common.model.constant.City;
import com.pubinfo.passbook.common.model.constant.StaffStatusEnum;
import com.pubinfo.passbook.common.model.dubbo.ESBServiceData;
import com.pubinfo.passbook.common.model.ruler.PayInformation;
import com.pubinfo.passbook.common.service.aviator.AviatorScriptService;
import com.pubinfo.passbook.common.service.dubbo.DubboService;
import com.pubinfo.passbook.common.service.master.*;
import com.pubinfo.passbook.common.service.ruler.CheckService;
import com.pubinfo.passbook.common.service.ruler.InformationService;
import com.pubinfo.passbook.common.service.ruler.RuleShengGongSiService;
import com.pubinfo.passbook.common.service.ruler.RuleWenZhouService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Service
public class RuleWenZhouServiceImpl implements RuleWenZhouService {

    @Autowired
    InformationService informationService;
    @Autowired
    TWiteoffShareAttachmentService shareAttachmentService;
    @Autowired
    TSubsidiaryInfoMapper infoMapper;
    @Autowired
    AviatorScriptService scriptService;
    @Autowired
    CheckService ruleService;
    @Autowired
    DubboService dubboService;
    @Autowired
    RuleShengGongSiService shengGongSiService;
    @Autowired
    TRuleParamService paramService;
    private int YEAR = 2021;

    @Autowired
    TRuleUserWiteoffService witeoffService;
    @Autowired
    TRuleGenusService genusService;
    @Autowired
    TRuleUserWiteoffMapper witeoffMapper;

    @Autowired
    TRuleFormulaService formulaService;

    @Override
    public BigDecimal municipalLevel(CityInfo info, Map<String, Object> env, Boolean isFront, List<PayInformation> payInformations) {
        StringBuilder details = new StringBuilder();
        //特殊病种,或者是特殊人群,走下面
        BigDecimal sum = new BigDecimal(0);
        Set<String> detailsSet = new HashSet<>();
        //   List<PayInformation> payInformations = informationService.listInformationFromPassbook(jobDTO.getInvoiceIds());
        String idNo = payInformations.get(0).getPayerPartyCode(); //报账人的身份证号
        String statusName = dubboService.getPersonsDetailByStatus(idNo);
        Integer status = StaffStatusEnum.getEnumByStatus(statusName).getCode();
        //离休的不报销
        if (status.equals(3)) {
            detailsSet.add("离休不报销");
            return sum;
        }
        BigDecimal fundPayAmounts = BigDecimal.ZERO;
        BigDecimal sumAmountSelfs = BigDecimal.ZERO;
        BigDecimal sumAllAmountSelfs = BigDecimal.ZERO;
        BigDecimal totalAmounts = BigDecimal.ZERO;
        for (PayInformation payInformation : payInformations) {
            BigDecimal fundPayAmount = payInformation.getFundPayAmount();
            if (fundPayAmount.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                fundPayAmount = BigDecimal.ZERO;
            }
            fundPayAmounts = fundPayAmounts.add(fundPayAmount);
            //获取自费项目总数
            BigDecimal sumAmountSelf = ruleService.sumAmountSelf(payInformation.getDetailsList());
            //计算
            if (sumAmountSelf.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                sumAmountSelf = BigDecimal.ZERO;
            }
            sumAmountSelfs = sumAmountSelfs.add(sumAmountSelf);
            BigDecimal selfpaymentCost = payInformation.getSelfpaymentCost();
            //计算
            if (selfpaymentCost.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                selfpaymentCost = BigDecimal.ZERO;
            }
            sumAllAmountSelfs = sumAmountSelfs.add(selfpaymentCost);
            BigDecimal totalAmount = payInformation.getTotalAmount();
            if (totalAmount.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                totalAmount = BigDecimal.ZERO;
            }
            totalAmounts = totalAmounts.add(totalAmount);
        }
        env.put("fundPayAmount", fundPayAmounts);
        env.put("sumAmountSelf", sumAmountSelfs);
        env.put("totalAmount", totalAmounts);
        env.put("sumAllAmountSelf", sumAllAmountSelfs);
        //计算处理住院逻辑
        String key;
        BigDecimal executeMoney;
        if (ruleService.isSpecialDiseases(info.getDistrictName(), idNo) || ruleService.isSpecialUser(info.getDistrictName(), idNo)) {
            /**
             * 子单报销金额计算方法
             * {劳模门诊|劳模住院|特殊门诊|特殊病住院}报销比例 =  医保统筹基金支付/90% * ((1-90%)+（诊察费自费+检查费自费+化验费自费+卫生材料费自费+中成药费自费+中药饮片费自费+西药费自费）*30%
             */
            //获取医保统筹基金支付 isNeedAudit

            if (status.equals(0)) {
                //退休人员
//        executeMoney = scriptService.execute("(fundPayAmount/txtcjjzf)*(1-txtcjjzf)+sumAmountSelf*zyzfbx", env);
                key = "special_departure";
            } else {
                //在职和内退
//        executeMoney = scriptService.execute("(fundPayAmount/zjtcjjzf)*(1-zjtcjjzf)+sumAmountSelf*zyzfbx", env);
                key = "special_job_early_retirement";
            }

        } else if (payInformations.get(0).getReimbursementType() == 1) {
            //走普通住院报销
            /**子单报销金额计算方法
             * 普通病在职住院报销比例 =  医保统筹基金支付/90% * ((1-90%)+（（诊察费自费+检查费自费+化验费自费+卫生材料费自费+中成药费自费+中药饮片费自费+西药费自费）-8000）*30%
             */
            // scriptService.execute("(fundPayAmount/0.9)*(1-0.9)", env);//如果超过8000,则报销8000以上的30% ,如果不超过,则不报销
            if (status.equals(0)) {
                //退休
                key = "reimbursement_type_departure";
//        executeMoney = scriptService.execute("je =(fundPayAmount/txtcjjzf)*(1-txtcjjzf);  if(sumAmountSelf>zyzfbxzd){return je +sumAmountSelf*zyzfbx;} return je;", env);
            } else {
                //在职和内退
                key = "reimbursement_type_oher";
                //      executeMoney = scriptService.execute("je = (fundPayAmount/zjtcjjzf)*(1-zjtcjjzf); if(sumAmountSelf>zyzfbxzd){ return je +sumAmountSelf*zyzfbx;} return je;", env);
            }
            //先计算所有票据医保统筹基金相关的报销金额,再加上自费项目报销金额

        } else {
            //处理门诊逻辑，温州门诊纸质票据还有很多，目前先不做
            /**
             * 在职员工普通病门诊报销比例 = ( (发票总额-自费的)-10000)*70%
             */
            //处理门诊逻辑，温州门诊纸质票据还有很多，目前先不做
            //计算
            // scriptService.execute("(passbookSum-sumAllAmountSelf-10000)*0.7", env);
            if (status.equals(1)) {
                key = "general_opc_job";
                //   executeMoney = scriptService.execute("(totalAmount-sumAllAmountSelf-startLine)*zjygptbmzbx", env);
            } else {
                key = "general_opc_departure";
                //  executeMoney = scriptService.execute("(totalAmount-sumAllAmountSelf-startLine)*txygptbmzbx", env);
            }

        }
        TRuleFormula formula = (TRuleFormula) env.get(key);
        executeMoney = scriptService.execute(formula.getFormula(), env);
        detailsSet.add(formula.getDetalis());

        //等于1 时说明大于0,则可以设置报销金额,为负数不设置报销金额
        if (executeMoney.compareTo(BigDecimal.ZERO) == 1) {
            sum = sum.add(executeMoney);
        }
        env.put("user-detalis", CollUtil.join(detailsSet, ";"));
        return sum;
    }

    @Override
    public BigDecimal yueQing(CityInfo info,
                              List<PayInformation> payInformations, Map<String, Object> env) {
        BigDecimal sum = new BigDecimal(0);
        StringBuilder details = new StringBuilder();
        Set<String> detailsSet = new HashSet<>();
        String idNo = payInformations.get(0).getPayerPartyCode(); //报账人的身份证号

        ESBServiceData.CertDetail certDetail = dubboService.getPersonsDetailByIdNo(idNo);
        //工龄
        Integer length_of_service = Integer.valueOf(certDetail.getWorkTime());
        //当前日期
        Integer current = Integer.valueOf(new Date().toInstant().toString().substring(0, 10).replaceAll("-", ""));
        //出生日期
        Integer birth = Integer.valueOf(certDetail.getBirthDate().replaceAll("-", ""));
        //年龄
        Integer age = (current - birth) / 10000;
        //工作状态   0：退休  1：在职/内退  2:离休
        Integer working = StaffStatusEnum.getEnumByStatus(certDetail.getStaffStatus()).getCode();
        //个人有效支付总金额
        BigDecimal totalAvailabilityPays = new BigDecimal(0);

        //不能报销的金额
        BigDecimal noAllowance = new BigDecimal(0);
        //特殊人群
        for (PayInformation payInformation : payInformations) {
            BigDecimal ownPay = payInformation.getOwnPayAmount();
            BigDecimal fundPayAmount = payInformation.getFundPayAmount();
            if (ownPay.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                ownPay = BigDecimal.ZERO;
            }
            //个人有效支付=个人现金支付-不能报销的金额
            BigDecimal availabilityPay = ownPay.subtract(noAllowance);
            totalAvailabilityPays = totalAvailabilityPays.add(availabilityPay);

        }
        String key = "";
        env.put("totalAvailabilityPay", totalAvailabilityPays);
        PayInformation payInformation = payInformations.get(0);
        if (ruleService.isSpecialDiseases(info.getDistrictName(), idNo) || ruleService.isSpecialUser(info.getDistrictName(), idNo)) {
            sum = totalAvailabilityPays;
        } else if (working == 1 && length_of_service < 15) {
            //在职且工龄在15年以下
            //sum = scriptService.execute("totalAvailabilityPay*reimbursementRate1", env);
            key = "employed_less_fifteen";
        } else if (working == 1 && length_of_service >= 15 && length_of_service < 25
                && payInformation.getReimbursementType() == 1) {
            //在职工龄在15~25之间的住院
            //sum = scriptService.execute("totalAvailabilityPay*reimbursementRate2", env);
            key = "employed_less_twenty-five";
        } else if (payInformation.getReimbursementType() == 0 &&
                ((age >= 70 && working == 0) || (length_of_service >= 25 && working == 1))) {
            //满70周岁以上的退休门诊报销
            //工龄在25年之上的在职门诊报销
            //sum = scriptService.execute("totalAvailabilityPay*reimbursementRate3", env);
            key = "more_seventy_or_twenty-five";
        } else {
            //在职且工龄在15~25之间的门诊
            //在职且工龄在25以上的住院
            //退休且年龄在70以下的门诊
            //退休的住院
            //sum = scriptService.execute("totalAvailabilityPay*reimbursementRate4", env);
            key = "yueqing_other";
        }
        //门诊报销有最高限额
        TRuleFormula formula = (TRuleFormula) env.get(key);
        sum = scriptService.execute(formula.getFormula(), env);
        detailsSet.add(formula.getDetalis());
        if (payInformation.getReimbursementType() == 0) {
            //退休限额3000
            BigDecimal offmaxquotas = new BigDecimal(String.valueOf(env.get("offmaxauotas")));
            //在职限额1500
            BigDecimal onmaxquotas = new BigDecimal(String.valueOf(env.get("onmaxauotas")));
            BigDecimal maxquotas = working == 0 ? offmaxquotas : onmaxquotas;
            if (sum.compareTo(maxquotas) == 1) {
                env.put("sum", sum);
                env.put("maxquotas", maxquotas);
                TRuleFormula excess = (TRuleFormula) env.get("yueqing_excess");
                sum = scriptService.execute(excess.getFormula(), env);

                detailsSet.add(excess.getDetalis());
            }
        }
        env.put("user-detalis", CollUtil.join(detailsSet, ";"));
        return sum;
    }

    @Override
    public BigDecimal taiShun(CityInfo info, Map<String, Object> paramEnv, Boolean isFront, List<PayInformation> payInformations) {
        BigDecimal sum = new BigDecimal(0);
        PayInformation payInformat = payInformations.get(0);
        String idNo = payInformat.getPayerPartyCode(); //报账人的身份证号
        String statusName = dubboService.getPersonsDetailByStatus(idNo);
        String acct = dubboService.getPersonsDetailByAcct(idNo);
        Integer status = StaffStatusEnum.getEnumByStatus(statusName).getCode();
        Set<String> detailsSet = new HashSet<>();
        //没有离休
        if (status.equals(3)) {
            return sum;
        }
        //自费金额
        BigDecimal sumAmountSelfs = new BigDecimal(0);
        //医保统筹基金支付金额
        BigDecimal fundPayAmounts = new BigDecimal(0);
        //票据总金额
        BigDecimal totalAmounts = new BigDecimal(0);
        //最高的起付线
        BigDecimal startPayments = new BigDecimal(0);
        for (PayInformation payInformation : payInformations) {
            //获取医保统筹基金支付
            BigDecimal fundPayAmount = payInformation.getFundPayAmount();
            if (fundPayAmount.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                fundPayAmount = BigDecimal.ZERO;
            }
            fundPayAmounts = fundPayAmounts.add(fundPayAmount);
            //获取自费项目总数
            BigDecimal sumAmountSelf = payInformation.getSelfpaymentCost();
            if (sumAmountSelf.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                sumAmountSelf = BigDecimal.ZERO;
            }
            sumAmountSelfs = sumAmountSelfs.add(sumAmountSelf);
            //获取票据总金额
            BigDecimal totalAmount = payInformation.getTotalAmount();
            if (totalAmount.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                totalAmount = BigDecimal.ZERO;
            }
            totalAmounts = totalAmounts.add(totalAmount);
            //获取票据的起付线
        }
        paramEnv.put("sumAmountSelfs", sumAmountSelfs);
        paramEnv.put("fundPayAmounts", fundPayAmounts);
        paramEnv.put("totalAmounts", totalAmounts);
        //处理住院逻辑
        if (payInformat.getReimbursementType() == 1) {
            //走普通住院报销
            /**reimbursement_type_job_departure
             * [在职|退休] 住院金额=（所有票据总金额-起付标准）-统筹支付金额-自费金额
             */
            paramEnv.put("startPayments", ruleService.getStartPayments(paramEnv, payInformations));
            TRuleFormula formula = (TRuleFormula) paramEnv.get("tai_shun_hospital");
            BigDecimal executeMoney = scriptService.execute(formula.getFormula(), paramEnv);
            detailsSet.add(formula.getDetalis());
            sum = sum.add(executeMoney);
            //如果计算得出报销金额小于0，无法报销
            if (executeMoney.compareTo(BigDecimal.ZERO) <= 0) {
                sum = BigDecimal.ZERO;
            }
        } else {
            //处理门诊逻辑，温州门诊纸质票据还有很多，目前先不做
            /**
             * 退休门诊超过10000不超过15000报销 金额=（总金额-10000）*80%
             * 退休门诊超过15000报销 金额=（15000-10000）*80%+（总金额-15000）*50%
             * 在职门诊超过10000不超过15000报销 金额=（总金额-10000）*70%
             * 在职门诊超过15000报销 金额=（15000-10000）*70%+（总金额-15000）*50%
             */ //      }
            //获取票据总金额
            //超过10000才可以报销
            String key = null;
            BigDecimal historySum = witeoffMapper.countSumByAcct(acct, 330601);
            BigDecimal constant1 = new BigDecimal(10000);
            if (totalAmounts.compareTo(constant1) == 1 || historySum.compareTo(BigDecimal.ZERO) == 1) {
                //最大一档报销金额
                BigDecimal maxSum = BigDecimal.ZERO;
                if (status.equals(1)) {
                    //在职为3500
                    maxSum = new BigDecimal("3500");
                } else if (status.equals(0) || status.equals(2)) {
                    //退休为4000
                    maxSum = new BigDecimal("4000");
                }
                //已报销金额大于一档报销金额，剩下的必定只走二档
                if (historySum.compareTo(maxSum) == 1) {
                    //无论在职和退休都是报销50%
                    key = "tai_shun_two";
                } else {
                    BigDecimal historyAmounts = BigDecimal.ZERO;
                    //含有一档的情况下先计算出原先纳入报账的金额加上，最后减去已经报销的金额
                    if (status.equals(1)) {
                        //在职报销比例为70%
                        historyAmounts = historySum.divide(new BigDecimal(0.7), 10, BigDecimal.ROUND_HALF_UP).add(constant1);
                    } else if (status.equals(0) || status.equals(2)) {
                        //退休报销比例为80%
                        historyAmounts = historySum.divide(new BigDecimal(0.8), 10, BigDecimal.ROUND_HALF_UP).add(constant1);
                    }
                    paramEnv.put("historyAmounts", historyAmounts);
                    paramEnv.put("historySum", historySum);
                    //如果加上报销的金额依然在一档中
                    if (totalAmounts.add(historyAmounts).compareTo(new BigDecimal("15000")) <= 0) {
                        if (status.equals(1)) {
                            /**
                             * 报销金额=(totalAmounts+historyAmounts-10000)*70%-historySum
                             * 报销金额=（纳入报销的金额+历史纳入报销金额-10000）*70%-已经报销的金额
                             */
                            key = "tai_shun_opc_job_less";
                        } else if (status.equals(0) || status.equals(2)) {
                            /**
                             * 报销金额=(totalAmounts+historyAmounts-10000)*80%-historySum
                             * 报销金额=（纳入报销的金额+历史纳入报销金额-10000）*80%-已经报销的金额
                             */
                            key = "tai_shun_opc_departure_less";
                        }
                    }
                    //加上报销的金额已经超过一档报销线
                    else {
                        if (status.equals(1)) {
                            /**
                             * 报销金额=(15000-10000)*70%+(totalAmounts-15000+historyAmounts)*50%-historySum
                             * 报销金额=（15000-10000）*70%+（纳入报销的金额+历史纳入报销金额-15000）*50%-已经报销的金额
                             */
                            key = "tai_shun_opc_job_more";
                        } else if (status.equals(0) || status.equals(2)) {
                            /**
                             * 报销金额=(15000-10000)*80%+(totalAmounts-15000+historyAmounts)*50%-historySum
                             * 报销金额=（15000-10000）*80%+（纳入报销的金额+历史纳入报销金额-15000）*50%-已经报销的金额
                             */
                            key = "tai_shun_opc_departure_more";
                        }
                    }
                }
                TRuleFormula formula = (TRuleFormula) paramEnv.get(key);
                BigDecimal executeMoney = scriptService.execute(formula.getFormula(), paramEnv);
                detailsSet.add(formula.getDetalis());

                sum = sum.add(executeMoney);
            } else {
                detailsSet.add("金额未超过10000无法报销");
            }
        }
        paramEnv.put("user-detalis", CollUtil.join(detailsSet, ";"));
        return sum;
    }

    @Override
    public BigDecimal longGang(CityInfo info, Map<String, Object> paramEnv, Boolean isFront, List<PayInformation> payInformations) {
        BigDecimal sum = new BigDecimal(0);
        //   List<PayInformation> payInformations = informationService.listInformationFromPassbook(jobDTO.getInvoiceIds());
        PayInformation pay = payInformations.get(0);
        String idNo = pay.getPayerPartyCode(); //报账人的身份证号
        String statusName = dubboService.getPersonsDetailByStatus(idNo);
        String acct = dubboService.getPersonsDetailByAcct(idNo);
        Integer status = StaffStatusEnum.getEnumByStatus(statusName).getCode();
        //没有离休，如果遇到离休直接退出
        if (status.equals(3)) {
            return sum;
        }
        //自费金额
        BigDecimal sumAmountSelfs = BigDecimal.ZERO;
        //医保统筹基金支付金额
        BigDecimal selfpaymentAmounts = BigDecimal.ZERO;
        BigDecimal fundPayAmounts = BigDecimal.ZERO;
        BigDecimal totalAmounts = BigDecimal.ZERO;
        Map<String, BigDecimal> types = new HashMap();
        Set<String> detailsSet = new HashSet<>();
        types.put("甲", new BigDecimal(1));
        types.put("乙", new BigDecimal(1));
        for (PayInformation payInformation : payInformations) {
            BigDecimal sumAmountSelf = informationService.getSumAmountSelfByType(payInformation.getEInvoiceId(), types);
            if (sumAmountSelf.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                sumAmountSelf = BigDecimal.ZERO;
            }
            sumAmountSelfs = sumAmountSelfs.add(sumAmountSelf);
            //自负总金额
            //获取自负项目总数
            BigDecimal selfpaymentAmount = payInformation.getSelfpaymentAmount();
            if (selfpaymentAmount.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                selfpaymentAmount = BigDecimal.ZERO;
            }
            selfpaymentAmounts = selfpaymentAmounts.add(selfpaymentAmount);

            BigDecimal fundPayAmount = payInformation.getFundPayAmount();
            if (fundPayAmount.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                fundPayAmount = BigDecimal.ZERO;
            }
            fundPayAmounts = fundPayAmounts.add(fundPayAmount);

            BigDecimal totalAmount = payInformation.getTotalAmount();
            if (totalAmount.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                totalAmount = BigDecimal.ZERO;
            }
            totalAmounts = totalAmounts.add(totalAmount);
        }

        paramEnv.put("fundPayAmounts", fundPayAmounts);
        paramEnv.put("sumAmountSelfs", sumAmountSelfs);
        paramEnv.put("selfpaymentAmounts", selfpaymentAmounts);
        //  paramEnv.put("totalAmounts", totalAmounts);
        //处理住院逻辑
        if (pay.getReimbursementType() == 1) {
            //走普通住院报销
            /** long_gang_hospital selfpaymentAmounts+sumAmountSelfs*hospitalization
             * 自负金额+自费金额(不含丙类药) * 50%(年总报销不超过10000)
             * 15万以下的不能报
             *15万<（总额-封顶线）<45万的部分，自负金额+自费金额(不含丙类药) * 50%
             * 45万以上的不报
             */
            int amounts = totalAmounts.compareTo(new BigDecimal(150000));
            if (amounts == 1) {
                //不分在职离职

                String key = "long_gang_hospital";
                TRuleFormula formula = (TRuleFormula) paramEnv.get(key);
                BigDecimal executeMoney = scriptService.execute(formula.getFormula(), paramEnv);
                detailsSet.add(formula.getDetalis());
                //年总报销额不超过50000
                sum = sum.add(executeMoney).min(new BigDecimal(String.valueOf(paramEnv.get("hospitalizationLimitLine"))));
                BigDecimal historySum = witeoffMapper.countSumByAcct(acct, 330602);
                if (historySum.add(sum).compareTo(new BigDecimal(50000)) == 1) { //如果大于最大金额,则只能报账小于最大金额部分
                    sum = new BigDecimal(50000).subtract(historySum);

                    detailsSet.add("年总报销额不超过50000");
                }
            } else {
                //小于等于150000，不能报
                detailsSet.add("15万以下的不能报");
            }

        } else {
            /**
             * 统筹总支付超过10000  long_gang_opc
             * 本年账户、历年账户为0后，个人现金支付中 年自负总额*100% +年自费总额(不含丙类) * 50%
             */
            //获取自费项目总数,仅仅报销甲类、乙类项目
            //只有统筹支付金额超过10000才能报销
            BigDecimal constant = new BigDecimal(String.valueOf(paramEnv.get("startLine")));
            BigDecimal historySum = witeoffMapper.countSumByAcct(acct, 330601);
            if (fundPayAmounts.compareTo(constant) == 1 || historySum.compareTo(BigDecimal.ZERO) == 1) {
                String key = "long_gang_opc";
                TRuleFormula formula = (TRuleFormula) paramEnv.get(key);
                BigDecimal executeMoney = scriptService.execute(formula.getFormula(), paramEnv);
                detailsSet.add(formula.getDetalis());
                sum = sum.add(executeMoney);
            }
            //查询是否超过报销最大限制
            if (historySum.add(sum).compareTo(new BigDecimal(10000)) == 1) { //如果大于最大金额,则只能报账小于最大金额部分
                sum = new BigDecimal(10000).subtract(historySum);
            }
        }
        paramEnv.put("user-detalis", CollUtil.join(detailsSet, ";"));
        return sum;
    }

    @Override
    public BigDecimal wenCheng(CityInfo info, Map<String, Object> paramEnv, Boolean isFront, PayInformation payInformation) {
        BigDecimal sum = new BigDecimal(0);
        //   List<PayInformation> payInformations = informationService.listInformationFromPassbook(jobDTO.getInvoiceIds());
        String idNo = payInformation.getPayerPartyCode(); //报账人的身份证号

        String statusName = dubboService.getPersonsDetailByStatus(idNo);
        Integer status = StaffStatusEnum.getEnumByStatus(statusName).getCode();

        Set<String> detailsSet = new HashSet<>();
        //如果是接口报账,没有到年度报账时间,返回0;
//    if (!isFront && ruleService.isFannualDate(1)) {
//      return sum;
//    }

        if (ruleService.isSpecialDiseases(info.getDistrictName(), idNo) || payInformation.getReimbursementType() == 1) {
            /**
             * 特殊病和住院一起报销
             * [在职|退休|特殊病种]  住院   (统筹支付金额/医院等级的住院报销比例-住院统筹基金支付-起付线个人支付) *100%
             * (在票据中的统筹支付金额计算出的可报销金额中已经减去起付线）
             * 在职 起付线 600 医保比例 90%
             * 退休 起付线 400 医保比例 95%
             *
             */
            //获取医保统筹基金支付总费用
            BigDecimal fundPayAmounts = payInformation.getFundPayAmount();

            //计算
            paramEnv.put("fundPayAmounts", fundPayAmounts);
            //统筹支付金额得出的符合医保费用已经减去起付线
            BigDecimal executeMoney = new BigDecimal(0);
            String key = null;
            //在职
            if (status.equals(1)) {
                key = "wen_chen_hospital_job";
            }
            //退休或内退
            else if (status.equals(0) || status.equals(2)) {
                key = "wen_chen_hospital_departure";
            }
            TRuleFormula formula = (TRuleFormula) paramEnv.get(key);
            executeMoney = scriptService.execute(formula.getFormula(), paramEnv);

            detailsSet.add(formula.getDetalis());
            sum = sum.add(executeMoney);

        } else {
            /**
             *
             * 退休               门诊  （统筹支付金额/医院等级的门诊报销比例-个人账户支付-门诊医疗统筹年封顶线）*80%（最多报销4000）((15000-10000)*80%)
             * 在职               门诊  （统筹支付金额/医院等级的门诊报销比例-个人账户支付-门诊医疗统筹年封顶线）*70%（最多报销3500）((15000-10000)*70%)
             * 统筹封顶线 10000
             * 三级报销60% 二级报销70% 一级报销80%
             *
             */
            //获取医保统筹基金支付总费用
            BigDecimal fundPayAmounts = new BigDecimal(0);
            //统筹支付费用
            BigDecimal fundPayAmount = payInformation.getFundPayAmount();
            String startPayment = payInformation.getOrgType();
            fundPayAmounts = fundPayAmounts.add(fundPayAmount);
            //获取个人账户支付费用
            BigDecimal accountPayAmounts = payInformation.getAccountPayAmount();

            paramEnv.put("fundPayAmounts", fundPayAmounts);
            paramEnv.put("accountPayAmounts", accountPayAmounts);
            BigDecimal executeMoney = new BigDecimal(0);
            String key = null;
            if (startPayment.contains("三级")) {
                if (status.equals(1)) {
                    key = "wen_chen_opc_job_three";
                }
                //退休或内退
                else if (status.equals(0) || status.equals(2)) {
                    key = "wen_chen_opc_departure_three";
                }
            } else if (startPayment.contains("二级")) {
                if (status.equals(1)) {
                    key = "wen_chen_opc_job_two";
                }
                //退休或内退
                else if (status.equals(0) || status.equals(2)) {
                    key = "wen_chen_opc_departure_two";
                }
            } else if (startPayment.contains("一级")) {
                if (status.equals(1)) {
                    key = "wen_chen_opc_job_one";
                }
                //退休或内退
                else if (status.equals(0) || status.equals(2)) {
                    key = "wen_chen_opc_departure_one";
                }
            }
            TRuleFormula formula = (TRuleFormula) paramEnv.get(key);
            executeMoney = scriptService.execute(formula.getFormula(), paramEnv);

            detailsSet.add(formula.getDetalis());
            executeMoney = executeMoney.min(new BigDecimal(String.valueOf(paramEnv.get("cutOffLine"))).subtract(new BigDecimal(String.valueOf(paramEnv.get("startLine")))));
            //只有可报销费用大于0才报销
            if (executeMoney.compareTo(BigDecimal.ZERO) == 1) {
                sum = sum.add(executeMoney);
            }
        }
        paramEnv.put("user-detalis", CollUtil.join(detailsSet, ";"));
        return sum;
    }

    @Override
    public BigDecimal yongJia(CityInfo info, Map<String, Object> paramEnv, Boolean isFront, List<PayInformation> payInformations) {
        //特殊病种,或者是特殊人群,走下面
        BigDecimal sum = new BigDecimal(0);
        PayInformation pay = payInformations.get(0);
        String idNo = pay.getPayerPartyCode(); //报账人的身份证号
        ESBServiceData.CertDetail certDetail = dubboService.getPersonsDetailByIdNo(idNo);
        Set<String> detailsSet = new HashSet<>();
        String statusName = certDetail.getStaffStatus();
        Integer status = StaffStatusEnum.getEnumByStatus(statusName).getCode();
        //离休的不报销
        if (status.equals(3)) {
            detailsSet.add("离休的不报销");
            return sum;
        }
        //工龄
        Integer workTime = Integer.valueOf(certDetail.getWorkTime());
        Integer age = certDetail.getAge(); //年龄
        BigDecimal matchingGrant = null;

        String key = null;
        //处理特殊人群逻辑  100%
        if (ruleService.isSpecialUser(info.getDistrictName(), idNo)) {
            detailsSet.add("特殊人群");
            key = "yongJiabybl10";
            matchingGrant = new BigDecimal(1);
            //处理患特殊病人群  90%
        } else if (ruleService.isSpecialDiseases(info.getDistrictName(), idNo)) {

            key = "yongJiabybl09";
            matchingGrant = new BigDecimal(0.9);
        } else if (pay.getReimbursementType() == 1) {
            //住院  //退休
            if (status.equals(0)) {
                key = "yongJiabybl08";
                matchingGrant = new BigDecimal(0.8);
            } else {
                //在职|内退员工
                if (workTime < 15) {
                    key = "yongJiabybl05";
                    matchingGrant = new BigDecimal(0.7);
                } else if (workTime >= 15 && workTime < 25) {
                    key = "yongJiabybl06";
                    matchingGrant = new BigDecimal(0.75);
                } else if (workTime >= 25) {
                    key = "yongJiabybl07";
                    matchingGrant = new BigDecimal(0.8);
                }
            }
        } else if (pay.getReimbursementType() == 0) {
            //门诊
            //退休
            if (status.equals(0)) {
                if (age < 70) {
                    key = "yongJiabybl03";
                    matchingGrant = new BigDecimal(0.8);
                } else {
                    key = "yongJiabybl04";
                    matchingGrant = new BigDecimal(0.85);
                }
            } else {
                //在职|内退员工
                if (workTime < 15) {
                    key = "yongJiabybl00";
                    matchingGrant = new BigDecimal(0.7);
                } else if (workTime >= 15 && workTime < 25) {
                    key = "yongJiabybl01";
                    matchingGrant = new BigDecimal(0.80);
                } else if (workTime >= 25) {
                    key = "yongJiabybl02";
                    matchingGrant = new BigDecimal(0.85);
                }
            }
        }
        BigDecimal sumAllAmountSelfs = BigDecimal.ZERO;
        BigDecimal sumAllSelfpaymentCares = BigDecimal.ZERO;
        BigDecimal sumAllownPayAmounts = BigDecimal.ZERO;
        for (PayInformation payInformation : payInformations) {
            BigDecimal sumAllAmountSelf = payInformation.getSelfpaymentCost(); //所有自费
            if (sumAllAmountSelf.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                sumAllAmountSelf = BigDecimal.ZERO;
            }
            sumAllAmountSelfs = sumAllAmountSelfs.add(sumAllAmountSelf);
            BigDecimal sumAllSelfpaymentCare = payInformation.getSelfpaymentCare();
            if (sumAllSelfpaymentCare.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                sumAllSelfpaymentCare = BigDecimal.ZERO;
            }
            sumAllSelfpaymentCares = sumAllSelfpaymentCares.add(sumAllSelfpaymentCare);
            BigDecimal sumAllownPayAmount = payInformation.getOwnPayAmount();
            if (sumAllownPayAmount.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                sumAllownPayAmount = BigDecimal.ZERO;
            }
            sumAllownPayAmounts = sumAllownPayAmounts.add(sumAllownPayAmount);
        }
        BigDecimal scale = (BigDecimal) paramEnv.get(key);
        TRuleFormula formula = (TRuleFormula) paramEnv.get("yongJia");
        paramEnv.put("matchingGrant", scale);
        paramEnv.put("sumAllAmountSelf", sumAllAmountSelfs);
        paramEnv.put("sumAllSelfpaymentCare", sumAllSelfpaymentCares);
        paramEnv.put("sumAllownPayAmount", sumAllownPayAmounts);

        detailsSet.add(String.format(formula.getDetalis(), scale.setScale(2, RoundingMode.HALF_UP)));
        BigDecimal executeMoney = scriptService.execute(formula.getFormula(), paramEnv);
        //  BigDecimal executeMoney = scriptService.execute("(sumAllownPayAmount-sumAllAmountSelf-sumAllSelfpaymentCare)*matchingGrant", paramEnv);
        //大于0时
        if (executeMoney.compareTo(BigDecimal.ZERO) == 1) {
            if (pay.getReimbursementType() == 0) {
                //门诊报销有限制 如果大于指定金额,则只能报销指定金额 在职员工1500元、退休人员3000元
                if (status.equals(0)) { //退休
                    if (executeMoney.compareTo(new BigDecimal(3000)) == 1) {
                        detailsSet.add("退休员工最高报销3000元");
                        executeMoney = new BigDecimal(3000);
                    }
                } else {
                    //在职
                    if (executeMoney.compareTo(new BigDecimal(1500)) == 1) {
                        executeMoney = new BigDecimal(1500);
                        detailsSet.add("在职员工最高报销1500元");
                    }
                }
            }
            sum = sum.add(executeMoney);
        }
        paramEnv.put("user-detalis", CollUtil.join(detailsSet, ";"));
        return sum;
    }

    @Override
    public BigDecimal cangNan(CityInfo info, Map<String, Object> env, Boolean isFront, List<PayInformation> payInformations) {
        //特殊病种,或者是特殊人群,走下面
        BigDecimal sum = new BigDecimal(0);
        PayInformation pay = payInformations.get(0);
        String idNo = pay.getPayerPartyCode(); //报账人的身份证号
        String statusName = dubboService.getPersonsDetailByStatus(idNo);
        String acct = dubboService.getPersonsDetailByAcct(idNo);
        Integer status = StaffStatusEnum.getEnumByStatus(statusName).getCode();
        StringBuilder details = new StringBuilder();
        Set<String> detailsSet = new HashSet<>();
        //离休的不报销
        if (status.equals(3)) {
            return sum;
        }
        BigDecimal sumAmountSelfs = new BigDecimal(0);
        BigDecimal selfpaymentCares = new BigDecimal(0);
        BigDecimal selfpaymentAmounts = new BigDecimal(0);
        BigDecimal totalAmounts = new BigDecimal(0);
        BigDecimal individualAccountPrevPayments = new BigDecimal(0);

        for (PayInformation payInformation : payInformations) {
            //历年支付
            BigDecimal individualAccountPrevPayment = payInformation.getIndividualAccountPrevPayment();
            if (individualAccountPrevPayment.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                individualAccountPrevPayment = BigDecimal.ZERO;
            }
            individualAccountPrevPayments = individualAccountPrevPayments.add(individualAccountPrevPayment);
            //个人现金支付
            BigDecimal sumAmountSelf = payInformation.getSelfpaymentCost();
            if (sumAmountSelf.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                sumAmountSelf = BigDecimal.ZERO;
            }
            sumAmountSelfs = sumAmountSelfs.add(sumAmountSelf);
            //个人现金支付
            BigDecimal ownPayAmount = payInformation.getOwnPayAmount();
            if (ownPayAmount.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                ownPayAmount = BigDecimal.ZERO;
            }
            //个人自理
            BigDecimal selfpaymentCare = payInformation.getSelfpaymentCare();
            if (selfpaymentCare.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                selfpaymentCare = BigDecimal.ZERO;
            }
            selfpaymentCares = selfpaymentCares.add(selfpaymentCare);
            //自负=个人现金支付-自费-自理
            selfpaymentAmounts = selfpaymentAmounts.add(ownPayAmount.subtract(sumAmountSelf).subtract(selfpaymentCare));

            BigDecimal totalAmount = payInformation.getTotalAmount();
            if (totalAmount.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                totalAmount = BigDecimal.ZERO;
            }
            totalAmounts = totalAmounts.add(totalAmount);

        }
        env.put("selfpaymentCare", selfpaymentCares);
        env.put("sumAmountSelf", sumAmountSelfs);
        env.put("selfpaymentAmount", selfpaymentAmounts);
        env.put("totalAmount", totalAmounts);
        env.put("individualAccountPrevPayments", individualAccountPrevPayments);
        String key = null;
        if (ruleService.isSpecialDiseases(info.getDistrictName(), idNo) || pay.getReimbursementType() == 1) {
            /**
             *  特殊病报销按住院标准处理: 住院报销金额=自负总额*100%+自费总额*50%+自理总额*0%+历年支付*100%
             *  selfpaymentAmount*1 +sumAmountSelf*0.5+selfpaymentCare*0.0+individualAccountPrevPayments*1
             */
            //计算
            key = "cang_nan_hospital";
            TRuleFormula formula = (TRuleFormula) env.get(key);
            BigDecimal executeMoney = scriptService.execute(formula.getFormula(), env);
            sum = sum.add(executeMoney);
            detailsSet.add(formula.getDetalis());
            //先计算所有票据医保统筹基金相关的报销金额,再加上自费项目报销金额
        } else if (pay.getReimbursementType() == 0) {
            //处理门诊逻辑，温州门诊纸质票据还有很多，目前先不做
            /**
             * 在职/退休 普通病报销金额 =（发票总额-10000）*50%
             * (totalAmount-10000)*0.5
             */

            BigDecimal historySum = witeoffMapper.countSumByAcct(acct, 330601);
            //当用户已经有报销金额说明已经超过起付线
            if (historySum.compareTo(BigDecimal.ZERO) == 1) {
                key = "cang_nan_opc_more";
                TRuleFormula formula = (TRuleFormula) env.get(key);
                BigDecimal executeMoney = scriptService.execute(formula.getFormula(), env);
                sum = sum.add(executeMoney);
                detailsSet.add(formula.getDetalis());
            } else {
                //计算
                key = "cang_nan_opc";
                TRuleFormula formula = (TRuleFormula) env.get(key);
                BigDecimal executeMoney = scriptService.execute(formula.getFormula(), env);
                //等于1 时说明大于0,则可以设置报销金额,为负数不设置报销金额
                if (executeMoney.compareTo(BigDecimal.ZERO) == 1) {
                    sum = sum.add(executeMoney);
                }
                detailsSet.add(formula.getDetalis());
            }
        }
        env.put("user-detalis", CollUtil.join(detailsSet, ";"));
        return sum;
    }

    @Override
    public BigDecimal ruiAn(List<PayInformation> payInformations, Map<String, Object> paramEnv) {
        BigDecimal sum = new BigDecimal(0);

        PayInformation pay = payInformations.get(0);
        String idNo = pay.getPayerPartyCode(); //报账人的身份证号
        ESBServiceData.CertDetail certDetail = dubboService.getPersonsDetailByIdNo(idNo);
        Integer status = StaffStatusEnum.getEnumByStatus(certDetail.getStaffStatus()).getCode();
        StringBuilder details = new StringBuilder();
        Set<String> detailsSet = new HashSet<>();
        //离休的不能报销
        if (status.equals(3)) {
            return sum;
        }
        BigDecimal totalFoudPayMounts = new BigDecimal(0);
        BigDecimal totalSelfpaymentCares = new BigDecimal(0);
        BigDecimal totalSelfpaymentCosts = new BigDecimal(0);
        BigDecimal totalAmounts = new BigDecimal(0);

        for (PayInformation payInformation : payInformations) {
            //医保统筹基金支付总金额
            BigDecimal totalFoudPayMount = payInformation.getFundPayAmount();
            if (totalFoudPayMount.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                totalFoudPayMount = BigDecimal.ZERO;
            }
            totalFoudPayMounts = totalFoudPayMounts.add(totalFoudPayMount);
            //自理总金额
            BigDecimal totalSelfpaymentCare = payInformation.getSelfpaymentCare();
            if (totalSelfpaymentCare.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                totalSelfpaymentCare = BigDecimal.ZERO;
            }
            totalSelfpaymentCares = totalSelfpaymentCares.add(totalSelfpaymentCare);
            //自费总金额
            BigDecimal totalSelfpaymentCost = payInformation.getSelfpaymentCost();
            if (totalSelfpaymentCost.equals(new BigDecimal(-0.0000999))) {
                paramEnv.put("isNeedAudit", true);
                totalSelfpaymentCost = BigDecimal.ZERO;
            }
            totalSelfpaymentCosts = totalFoudPayMounts.add(totalSelfpaymentCost);
        }
        paramEnv.put("totalFoudPayMount", totalFoudPayMounts);
        paramEnv.put("totalSelfpaymentCare", totalSelfpaymentCares);
        paramEnv.put("totalSelfpaymentCost", totalSelfpaymentCosts);
//    if (status.equals(0)) {
//      sum = scriptService.execute("totalFoudPayMount/0.7*(1-0.7)+(totalSelfpaymentCare+totalSelfpaymentCost)*0.7", env);
//    } else {
//      sum = scriptService.execute("totalFoudPayMount/0.7*(1-0.9)+(totalSelfpaymentCare+totalSelfpaymentCost)*0.65", env);
//    }
//    return sum;
        String key = null;
        if (status.equals(0)) {
            /**
             * 退休住院报销比例 =  (现金（支票）-合计其他自理费用)+合计其他自理费用*70%
             * totalFoudPayMount/0.7*(1-0.7)+(totalSelfpaymentCare+totalSelfpaymentCost)*0.7
             */
            key = "rui_an_departure";
        } else {
            /**
             * 在职|内退 住院报销比例 =  (现金（支票）-合计其他自理费用)+合计其他自理费用*65%
             * totalFoudPayMount/0.7*(1-0.9)+(totalSelfpaymentCare+totalSelfpaymentCost)*0.65
             */
            key = "rui_an_job";
        }
        TRuleFormula formula = (TRuleFormula) paramEnv.get(key);
        BigDecimal executeMoney = scriptService.execute(formula.getFormula(), paramEnv);
        detailsSet.add(formula.getDetalis());
        paramEnv.put("user-detalis", CollUtil.join(detailsSet, ";"));
        return sum.add(executeMoney);
    }

    @Override
    public BigDecimal pingYang(CityInfo info, Map<String, Object> env, List<PayInformation> payInformations) {
        BigDecimal sum;
        PayInformation pay = payInformations.get(0);
        String idNo = pay.getPayerPartyCode();
        StringBuilder details = new StringBuilder();
        Set<String> detailsSet = new HashSet<>();
        ESBServiceData.CertDetail certDetail = dubboService.getPersonsDetailByIdNo(idNo);
        Integer status = StaffStatusEnum.getEnumByStatus(certDetail.getStaffStatus()).getCode();
        BigDecimal ownPayAmounts = new BigDecimal(0);
        BigDecimal sumAmountSelfs = new BigDecimal(0);
        BigDecimal accountPayAmounts = new BigDecimal(0);
        BigDecimal costs = new BigDecimal(0);

        Map<String, BigDecimal> types = new HashMap();
        types.put("丙", new BigDecimal("1"));
        for (PayInformation payInformation : payInformations) {

            BigDecimal ownPayAmount = payInformation.getOwnPayAmount();
            if (ownPayAmount.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                ownPayAmount = BigDecimal.ZERO;
            }
            ownPayAmounts = ownPayAmounts.add(ownPayAmount);

            BigDecimal sumAmountSelf = informationService.getSumAmountSelfByType(payInformation.getEInvoiceId(), types);
            if (sumAmountSelf.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                sumAmountSelf = BigDecimal.ZERO;
            }
            sumAmountSelfs = sumAmountSelfs.add(sumAmountSelf);

            BigDecimal accountPayAmount = payInformation.getAccountPayAmount();
            if (accountPayAmount.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                accountPayAmount = BigDecimal.ZERO;
            }
            accountPayAmounts = accountPayAmounts.add(accountPayAmount);

            BigDecimal cost = payInformation.getSelfpaymentCost();
            if (cost.equals(new BigDecimal(-0.0000999))) {
                env.put("isNeedAudit", true);
                cost = BigDecimal.ZERO;
            }
            costs = costs.add(cost);
        }
        String key;
        BigDecimal percentage = new BigDecimal(0);
        env.put("ownPayAmounts", ownPayAmounts);
        env.put("sumAmountSelfs", sumAmountSelfs);
        env.put("accountPayAmounts", accountPayAmounts);
        if (pay.getReimbursementType() == 0) {
            //门诊逻辑

            if (status.equals(1)) {
                percentage = (BigDecimal) env.get("serviceretire"); //在职
            }
            if (status.equals(0)) {
                percentage = (BigDecimal) env.get("offretire"); //离职
            }

            if (ruleService.isSpecialUser(info.getDistrictName(), idNo)
                    || ruleService.isSpecialDiseases(info.getDistrictName(), idNo)) {
                percentage = (BigDecimal) env.get("special_opt");
            }
            env.put("percentage", percentage);
            //sum = scriptService.execute("(ownPayAmount-sumAmountSelf)*percentage", env);
            key = "pingyang_opt";
        } else {
            //住院逻辑
            //types.put("乙",new BigDecimal("1"));
            //types.put("丙",new BigDecimal("1"));
            if (ruleService.isSpecialUser(info.getDistrictName(), idNo)
                    || ruleService.isSpecialDiseases(info.getDistrictName(), idNo)) {
                costs = costs.multiply((BigDecimal) env.get("specialpeople"));
            }
            env.put("costs", costs);
            key = "pingyang_hospitalized";
            //sum = ownPayAmounts.add(accountPayAmounts).subtract(costs);
//    BigDecimal sumAmountSelf = informationService.getSumAmountSelfByType(payInformation.getEInvoiceId(), types);
        }
        TRuleFormula formula = (TRuleFormula) env.get(key);
        sum = scriptService.execute(formula.getFormula(), env);
        detailsSet.add(formula.getDetalis());
        env.put("user-detalis", CollUtil.join(detailsSet, ";"));
        return sum;
    }

    @Override
    public JSONObject testSum(List<String> passbookIds) {

        List<PayInformation> payInformations = informationService.listInformationFromPassbook(passbookIds);
        List<CityInfo> infos = infoMapper.findCityInfo();
        JSONObject jsonObject = new JSONObject();
        for (CityInfo info : infos) {
            Class<? extends City.Type> clas = City.get(info.getCityName());
            String districtName = info.getDistrictName();
            //查询区县参数集
            Map<String, Object> paramEnv = paramService.selectRuleParam(info.getDisId());
            Map<String, TRuleFormula> ruleFormulaMap = formulaService.findFormulaByDistrictId(info.getDisId());
            if (ruleFormulaMap.isEmpty()) continue;
            paramEnv.putAll(ruleFormulaMap);
            BigDecimal sum = new BigDecimal(0);
            BigDecimal reimburseSum = new BigDecimal(0);
            if (clas.equals(City.Type.WenZhou.class)) {
                City.Type.WenZhou district = City.Type.WenZhou.get(districtName);
                switch (district) {
                    case MUNICIPAL_LEVEL:
                        reimburseSum = municipalLevel(info, paramEnv, true, payInformations);
                        break;
                    case LONG_GANG:
                        reimburseSum = longGang(info, paramEnv, true, payInformations);
                        break;
                    case TAI_SHUN:
                        reimburseSum = taiShun(info, paramEnv, true, payInformations);
                        break;
                    case YUE_QING:
                        reimburseSum = yueQing(info, payInformations, paramEnv);
                        break;
                    case YONG_JIA:
                        reimburseSum = yongJia(info, paramEnv, true, payInformations);
                        break;
                    case CANG_NAN:
                        reimburseSum = cangNan(info, paramEnv, true, payInformations);
                        break;
                    case RY_AN:
                        reimburseSum = ruiAn(payInformations, paramEnv);
                        break;
                    case PING_YANG:
//            reimburseSum = pingYang(info, paramEnv, payInformations);
                        break;
                    default:
                        break;
                }
            } else if (clas.equals(City.Type.ShengGongSi.class)) {
                //省公司规则统一
                reimburseSum = shengGongSiService.benbu(info, paramEnv, payInformations);
            }
            sum = sum.add(reimburseSum);

            jsonObject.put(info.getCityName() + "-" + districtName, sum.setScale(2, RoundingMode.HALF_UP).toPlainString());

        }
        return jsonObject;
    }
}
